#!/usr/bin/python

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#
#    This file is part of ICTP RegCM.
#    
#    Use of this source code is governed by an MIT-style license that can
#    be found in the LICENSE file or at
#
#         https://opensource.org/licenses/MIT.
#
#    ICTP RegCM is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

# Configuration script for the RegCM distribution by M. Scarcia

try:
    import os,sys,shutil,fileinput,subprocess
    oldpy = 0
    try :
        hasp25 = subprocess.check_output(['true'])
    except :
        oldpy = 1
except:
    import os,sys,shutil,fileinput
    oldpy = 1

def getresult(command):
    result = ""
    if (oldpy) :
        try:
            result = os.popen(command).read().strip()
        except:
            raise KeyError 
    else:
        try:
            result = subprocess.check_output(command.split()).strip()
        except:
            raise KeyError 
    return result

def main(argv):

    numargs = 4

    # command line args are:
    # 1 - compiler type
    # 2 - mpi/serial
    # 3 - band yes/no
    # 4 - clm yes/no
    # 5 - debug/production

    if (len(sys.argv) < numargs+1 ):
        print "Not enough command line arguments!!"
        sys.exit(1)

    os.system("clear")
    print "\tAutomatically configuring the RegCM distribution"
    print "\n\tConfiguration pattern",sys.argv[1]

    print "\tAssuming CWD as RegCM root..."
    regcm_root = os.getcwd()

    print "\tAssuming CWD/Bin for RegCM binaries..."
    bin_dir=regcm_root+"/Bin"

    if not os.path.isdir(bin_dir):
        try :
            os.mkdir(bin_dir)
        except OSError :
            print "\tCannot create",bin_dir,"! Aborting..."
            sys.exit(1)   

    nclib = ""
    ncinc = ""
    hdf5lib = ""
    
    compress = 0 # never use gzip
    
    nclib,ncinc = netcdf_search(nclib,ncinc)
    hdf5lib = hdf5_search(hdf5lib)

    # Defaults to 0 (it can still be set manually to 1)
    #dbg = int(sys.argv[5]) 
    dbg = 0

    # Parallel or serial?
    mpi = int(sys.argv[2])

    # Let's assume that the compiler is always mpif90
    # We can change that later
    if mpi == 1 :
        mpi_compiler="mpif90"

    # Band yes or no?
    band = int(sys.argv[3])

    # CLM yes or no?
    clm = int(sys.argv[4])

    # just a guideline to know what numbers mean...
    #print "\n  ****  The following compiler/architecture combinations \n\tare tested and known to work, please choose one:\n\n\t\t1. GNU Fortran v. 4.4 (Linux x86-64)\n\t\t2. Intel Fortran v. 10 or 11 (Linux x86-64)\n\t\t3. PGI Fortran v. 9 (Linux x86-64)\n\t\t4. IBM Xlf Compiler (generic AIX)\n\t\t5. IBM Xlf Compiler (Cineca SP6)\n\t\t6. Sun Ceres Fortran 95 v 8.3 r2008/01/28 (Linux x86-64)\n\t\t7. GNU+g95 Fortran compiler (Linux x86-64)\n\t\t8. Other"

    compiler = int(sys.argv[1])

    print "root =",regcm_root
    print "compiler =",compiler
    print "debug =",dbg
 
    # Start real stuff

    choose_template(regcm_root,compiler,dbg)

    if compiler == 4 or compiler == 5 :
        mpi_compiler = "mpxlf90"

#TAO: compiler was added as an argument to makefile_edit() so that a -M line
#could be added to the NetCDF include line for the Sun compilers
    if mpi == 1 :
        makefile_edit(regcm_root,bin_dir,nclib,ncinc,mpi,mpi_compiler,band,clm,compiler,compress)
    else :
        makefile_edit(regcm_root,bin_dir,nclib,ncinc,mpi,"",band,clm,compiler,compress)

    #If the user has chosen the Sun compilers:
    #Write a note to the user indicating that the -M line will need to be
    #commented out before postnc will compile.  This is because the fortran
    #portions of the program require the command line option '-M' to specify
    #the location of the NetCDF modules, whereas the C++ portion (postnc) does
    #not recognize this option.  The Sun compilers do not currently have an
    #option to ignore unrecognized command-line options, and the current 
    #Makefile.inc scheme requires that C++ and Fortran portions of the code
    #both use the same NetCDF Include flags.
    if compiler == 6 :
        print "\n\t###################################################################"
        print "\n\tNOTE: the '-M' portion of the NETCDFINC line in Makefile.inc will "
        print "\tneed to be commented out after all programs are compiled but before"
        print "\t'postnc' can be compiled.  Insert a '#' right before -M on that"
        print "\tline to do this."
        print "\n\t###################################################################"

    print "\n\t###################################################################"
    print "\t# Configuration complete! You should now be able to compile RegCM #"
    print "\t###################################################################\n"

def netcdf_search(nclib,ncinc):

    ncok=True

    try :
        nclib = getresult('nc-config --prefix')
        ncinc = getresult('nc-config --includedir')
    except KeyError , CalledProcessError :
        ncok=False

    # check for path in env variables
    try :
        path_a=os.environ['NETCDF']
        if (os.path.isdir(path_a)):
            if (os.path.isfile(path_a+"/lib/libnetcdf.a") or os.path.isfile(path_a+"/lib/libnetcdf.so")) and (os.path.isfile(path_a+"/include/netcdf.mod")):
                nclib = path_a+"/lib"
                ncinc = path_a+"/include"
            else :
                ncok=False
        else :
            if ncok:
              ncok=False
    except KeyError :
        ncok=False

    if not ncok:
        try :
            path_lib=os.environ['NETCDF_LIB']
            path_inc=os.environ['NETCDF_INC']
            if (os.path.isfile(path_lib+"/libnetcdf.a") or os.path.isfile(path_lib+"/libnetcdf.so")) and (os.path.isfile(path_inc+"/netcdf.mod")):
                nclib = path_lib
                ncinc = path_inc
                ncok=True
            else :
                ncok=False
        except KeyError :
            ncok=False

    if not ncok:
        path_a="/usr"
        if (os.path.isfile(path_a+"/lib/libnetcdf.a") or os.path.isfile(path_a+"/lib/libnetcdf.so")) and (os.path.isfile(path_a+"/include/netcdf.mod")):
            nclib = path_a+"/lib"
            ncinc = path_a+"/include"
            ncok=True
        elif (os.path.isfile(path_a+"/lib64/libnetcdf.a") or os.path.isfile(path_a+"/lib64/libnetcdf.so")) and (os.path.isfile(path_a+"/include/netcdf.mod")):
            nclib = path_a+"/lib64"
            ncinc = path_a+"/include"
            ncok=True
        else :
            ncok=False

    if ncok:
        print "\tNetCDF library found..."
        return nclib,ncinc
    else:
    	print "\tNetCDF not found! Cannot continue. Please provide a working NetCDF library."
       	os.sys.exit(1)

def hdf5_search(hdf5lib):

    libok = True
    
    try :
        path_a=os.environ['HDF5']
        print path_a
        if (os.path.isfile(path_a+"/lib/libhdf5.a") or os.path.isfile(path_a+"/lib/libhdf5.so")):
            hdf5lib = path_a+"/lib"
        else :
            libok=False
    except KeyError :
        libok=False

    if not libok:
        try :
            path_a=os.environ['HDF5_LIB']
            if (os.path.isfile(path_a+"/libhdf5.a") or os.path.isfile(path_a+"/libhdf5.so")):
                hdf5lib = path_a
                libok = True
            else :
                libok=False
        except KeyError :
            libok=False

    if not libok:
        path_a="/usr"
        if (os.path.isfile(path_a+"/lib/libhdf5.a") or os.path.isfile(path_a+"/lib/libhdf5.so")):
            hdf5lib = path_a+"/lib"
            libok=True
        elif (os.path.isfile(path_a+"/lib64/libhdf5.a") or os.path.isfile(path_a+"/lib64/libhdf5.so")):
            hdf5lib = path_a+"/lib64"
            libok=True
        else :
            libok=False

    if libok:
        print "\tHDF5 library found..."
        return hdf5lib
    else:
       	print "\tHDF5 not found! RegCM will not use NetCDF v4 features..."
      	return ""
    
    
def choose_template(regcm_root,compiler,dbg):

    choices = 8
    
    #print "chose template gets: ",compiler,dbg
    if dbg == 1 and compiler < choices :
        if compiler == 1 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_gnu4.4",regcm_root+"/Makefile.inc")
        elif compiler == 2 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_intel10+",regcm_root+"/Makefile.inc")
        elif compiler == 3 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_pgi9",regcm_root+"/Makefile.inc")
        elif compiler == 4 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_xlf",regcm_root+"/Makefile.inc")
        elif compiler == 5 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_sp6",regcm_root+"/Makefile.inc")
        elif compiler == 6 :   
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_sun8.3",regcm_root+"/Makefile.inc")
        elif compiler == 7 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_g95",regcm_root+"/Makefile.inc")
    elif dbg == 0 and compiler < choices :
        if compiler == 1 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_gnu4.4_debug",regcm_root+"/Makefile.inc")
        elif compiler == 2 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_intel10+_debug",regcm_root+"/Makefile.inc")
        elif compiler == 3 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_pgi9_debug",regcm_root+"/Makefile.inc")
        elif compiler == 4 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_xlf_debug",regcm_root+"/Makefile.inc")
        elif compiler == 5 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_sp6_debug",regcm_root+"/Makefile.inc")
        elif compiler == 6 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_sun8.3_debug",regcm_root+"/Makefile.inc")
        elif compiler == 7 :
            shutil.copyfile(regcm_root+"/Arch/Makefile.inc_g95_debug",regcm_root+"/Makefile.inc")
    else :
        shutil.copyfile(regcm_root+"/Arch/Makefile.inc_other",regcm_root+"/Makefile.inc")
    return

#TAO: compiler was added as an argument to makefile_edit() so that a -M line
#could be added to the NetCDF include line for the Sun compilers
def makefile_edit(regcm_root,bin_dir,nclib,ncinc,mpi,mpi_compiler,band,clm,compiler,compress) :

    for line in fileinput.FileInput(regcm_root+"/Makefile.inc",inplace=1):

        line=line.replace("!BAND",str(band))
        line=line.replace("!CLM",str(clm))
        
        line=line.replace("!REGCM_ROOT",regcm_root)
        line=line.replace("!BIN_DIR",bin_dir)

        #If the sun compilers are being used, also indicate the path
        #of the file netcdf.mod

        ncliblist = ""
        hdf5lib = ""
        try :
            ncliblist = getresult('nc-config --flibs')
            ncliblist = ncliblist.replace(' -Wl,--as-needed',' ')
            ncliblist = ncliblist.replace('-lmfhdf -ldf','-lmfhdf -ldf -ljpeg')
            hdf5lib = ""
        except KeyError , CalledProcessError :
            hdf5_search(hdf5lib)

        if not ncliblist == "" :
            if not compiler == 5 :
                if compiler == 6 :
                    line=line.replace("!NETCDFINC","-I"+ncinc+" -M"+ncinc)
                else :
                    line=line.replace("!NETCDFINC","-I"+ncinc)
                line=line.replace("!NETCDFLIB","-L"+nclib+' '+ncliblist)
                if (compress == 1) :
                    line=line.replace("CPPFLAGS =","CPPFLAGS = -DNETCDF4_HDF5")
        else :

            if not compiler == 5 :
                if compiler == 6 :
                    line=line.replace("!NETCDFINC","-I"+ncinc+" -M"+ncinc)
                else :
                    line=line.replace("!NETCDFINC","-I"+ncinc)

                if os.path.isfile(nclib+"/libnetcdff.a") or os.path.isfile(nclib+"/libnetcdff.so"):
                    if hdf5lib == "" :
                        line=line.replace("!NETCDFLIB","-L"+nclib+" -lnetcdff -lnetcdf")
                    else :
                        line=line.replace("!NETCDFLIB","-L"+nclib+" -lnetcdff -lnetcdf -L"+hdf5lib+" -lhdf5_hl -lhdf5")
                else :
                    if hdf5lib == "" :
                        line=line.replace("!NETCDFLIB","-L"+nclib+" -lnetcdf")
                    else :
                        line=line.replace("!NETCDFLIB","-L"+nclib+" -lnetcdf -L"+hdf5lib+" -lhdf5_hl -lhdf5")
                if (compress == 1):
                    line=line.replace("CPPFLAGS =","CPPFLAGS = -DNETCDF4_HDF5")

        if mpi == 1 :
            line=line.replace("# PARALLEL = MPP1","PARALLEL = MPP1")

            
        line=line.replace("!MPIF90",mpi_compiler)
    
        print line.rstrip()

    fileinput.close()

if __name__ == "__main__":
    main(sys.argv[1:])
